<?php
class Boss_Request {

    const URI = "/ysearch/%s/v1/%s";
    
    protected $_allowedVerticals = array('web', 'images', 'news');
    
    protected $_vertical;
    
    protected $_query;
    
    protected $_allowedParams = array(
        'universal' => array('appid', 'start', 'count', 'lang', 'region', 'strictlang', 'format', 'callback', 'sites', 'view', 'style'),
        'web' => array('filter', 'type', 'view', 'abstract'),
        'images' => array('filter', 'dimensions', 'refererurl', 'url'),
        'news' => array('age', 'orderby', 'view'),
    );
    
    protected $_params = array('format' => 'xml');
    
    public function __construct($query, $vertical = "web", Array $params = array()) {
    
        $this->setQuery($query)
             ->setVertical($vertical)
             ->setParams($params);
    
    }
    
    public function setQuery($query) {
    
        $this->_query = (string) $query;
        return $this;
    
    }
    
    public function getQuery() {
    
        return $this->_query;
    
    }
    
    public function setVertical($vertical) {
    
        $vertical = strtolower($vertical);
        if (!in_array($vertical, $this->_allowedVerticals)) {
            throw new Boss_Request_Exception("Unknown vertical: {$vertical}");
        }
        $this->_vertical = $vertical;
        return $this;
    
    }
    
    public function getVertical() {
    
        return $this->_vertical;
    
    }
    
    public function setParams(Array $params) {
    
        foreach ($params as $param => $value) {
            $this->setParam($param, $value);
        }
        return $this;
    
    }
        
    public function getParams() {
    
        return $this->_params;
    
    }
    
    public function setParam($name, $value) {
    
        $name = strtolower($name);
        if (!in_array($name, $this->_allowedParams['universal']) && !in_array($name, $this->_allowedParams[$this->getVertical()])) {
            throw new Boss_Request_Exception("Unknown parameter: {$name}");
        }
        $this->_params[$name] = $value;
    
    }
    
    public function getParam($param) {
    
        $param = strtolower($param);
        if (!array_key_exists($param, $this->_params)) {
            throw new Boss_Request_Exception("Parameter '{$param}' is not available");
        }
        return $this->_params[$param];
    
    }
    
    public function getUri() {
    
        $uri = sprintf(self::URI, $this->getVertical(), $this->escapeUri($this->getQuery()));
        $params = array();
        foreach ($this->getParams() as $name => $value) {
            $params[] = "{$name}=" . $this->escapeUri($value);
        }
        return $uri . '?' . implode('&', $params);
    
    }
    
    public function escapeUri($str) {
    
        return rawurlencode($str);
    
    }

}